package com.lmx;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Properties;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.lmx.common.constants.CommonConstants;
import com.lmx.common.context.ActionContextHolder;
import com.lmx.common.util.PropertiesFileUtil;
import com.lmx.persistence.service.DataProcessService;
import com.lmx.repoDomain.tmodel.Role;
import com.lmx.repoDomain.tmodel.UserPrivate;
import com.lmx.repoDomain.tmodel.UserSession;
import com.lmx.repoDomain.tmodel.business.User;

/**
 * Created by qin on 2016/6/8.
 */
@Configuration
@Component
public class SessionFilter extends OncePerRequestFilter {
	private static Log logger = LogFactory.getLog(SessionFilter.class);
	@Autowired
	private DataProcessService dataProcessService;

	private Properties properties = PropertiesFileUtil.getProperties("application.properties");

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
			FilterChain filterChain) throws IOException, ServletException {

		/*
		 * String action = request.getHeader("action");//获取事件类型
		 * if(StringUtils.isNotBlank(action) && !"null".equals(action)){
		 * logger.debug("当前事件   action : " + action);
		 * ActionContextHolder.getContext().setAction(action);//保存action }
		 * String userId = request.getHeader("ccd-user-id");
		 * if(StringUtils.isNotBlank(userId) && CommonUtil.isNumeric(userId)){
		 * User user= dataProcessService.findUserById(userId);
		 * ActionContextHolder.getContext().setUser(user); //设置当前用户 String token
		 * = request.getHeader("ccd-token");
		 * ActionContextHolder.getContext().setToken(token); logger.debug(
		 * "设置当前用户  userId : " + userId); }
		 */
		Long startTime = System.currentTimeMillis();
		String serverLocalFalg = properties.getProperty("serverFlag.local");
		int localFlag = 0;// 0 非本地服务
		// != false && notnull 是本地服务
		if (serverLocalFalg != null && !"false".equals(serverLocalFalg)) {
			localFlag = 1;// 1本地服务
		}
		String basePath = request.getScheme() + "://" + request.getServerName() + ":"
				+ request.getServerPort();
		String tenantId = request.getHeader("tenantId");// 获取事件类型
		if (StringUtils.isNotBlank(tenantId) && !"null".equals(tenantId)) {
			logger.debug("当前事件   tenantId : " + tenantId);
			ActionContextHolder.getContext().setTenantId(Long.parseLong(tenantId));// 保存tenantId
		} else {
			ActionContextHolder.getContext().setTenantId(null);// 去除tenantId
		}
		String type = request.getHeader("systype");
		if (StringUtils.isNumeric(type)) {
			ActionContextHolder.getContext().setType(new Integer(type));
		}
		String action = request.getHeader("action");// 获取事件类型
		if (StringUtils.isNotBlank(action) && !"null".equals(action)) {
			ActionContextHolder.getContext().setAction(action);// 保存action
		} else {
			ActionContextHolder.getContext().setAction(null);// 去除action
		}
		// 验证token
		if (!checkIsVerify(request)) {
		} else if (request.getRequestURI().startsWith("/api/")) {
			if (!checkToken(request, response)) {
				response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);// 未授权
																		// 401
				response.setHeader("access-status", "AUTHFAILED");// 访问验证失败
				return;
			} else {
				response.setHeader("access-status", "AUTHSUCC");// 访问验证成功
				// 保存登录信息
				String userId = request.getHeader("ccd-user-id");
				if (userId != null) {
					String tokenOld = ActionContextHolder.getUidTokenHolder().get(userId);
					UserSession userSession = ActionContextHolder.getEvaHolder().get(tokenOld);
					// User user= dataProcessService.findUserById(userId);
					if (userSession != null) {
						User user = new User();
						BeanUtils.copyProperties(userSession, user);
						ActionContextHolder.getContext().setUser(user); // 设置当前用户
					}
				}
				String token = request.getHeader("ccd-token");
				ActionContextHolder.getContext().setToken(token);
			}
		} else if (request.getRequestURI().startsWith("/backStand/")
				&& !request.getRequestURI().startsWith("/backStand/login")
				&& !request.getRequestURI().startsWith("/backStand/backgroundLogin")) {
			if (!checkBackStandUser(request)) {
				response.sendRedirect(basePath + "/backStand/login");
			}
		}

		// request转换 缓存Request 数据
		ServletRequest requestWrapper = null;
		if (request instanceof HttpServletRequest && localFlag == 0) {
			HttpServletRequest httpServletRequest = request;
			String method = httpServletRequest.getMethod().toUpperCase();
			String codeType = httpServletRequest.getContentType() == null ? "" : httpServletRequest
					.getContentType();
			// 文件上传不做处理
			if (("POST".equals(method) || "PATCH".equals(method))
					&& !codeType.contains("multipart/form-data")
					&& !request.getRequestURI().startsWith("/access/")
			// && httpServletRequest.getContentType().equalsIgnoreCase(
			// "application/json; charset=utf-8")
			) {
				requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
			}
		}

		if (requestWrapper == null) {
			dataProcessService.addLog(request, "");// 添加访问日志
			filterChain.doFilter(request, response);
		} else {
			BufferedReader br = requestWrapper.getReader();
			String str = null, retStr = "";
			while ((str = br.readLine()) != null) {
				retStr += str;
			}
			if (retStr.length() > 65000) {
				retStr = retStr.substring(0, 65000);
			}
			dataProcessService.addLog(request, retStr);// 添加访问日志
			filterChain.doFilter(requestWrapper, response);
		}

		Long endTime = System.currentTimeMillis();
		if (endTime - startTime > 5000) {
			logger.warn(request.getRequestURI() + " used time " + (endTime - startTime) + "ms");
		}
	}

	/**
	 * 验证token
	 *
	 * @param request
	 * @return flag
	 */
	public boolean checkToken(HttpServletRequest request, HttpServletResponse response) {
		// options请求不做校验
		if (request.getMethod().equalsIgnoreCase("options")) {
			logger.debug("options pass");
			// response.setStatus(204);
			return true;
		}
		if (StringUtils.isNotBlank(request.getHeader("reset-password"))
				|| CommonConstants.ACTION_RESET_PASSWORD.equals(request.getHeader("action"))) {
			return true;
		}
		Boolean flag = false;
		String token = request.getHeader("ccd-token");
		String userId = request.getHeader("ccd-user-id");
		String tenantId = request.getHeader("tenantId");
		UserSession user = ActionContextHolder.getEvaHolder().get(token);
		if (ActionContextHolder.getEvaHolder().get(token) != null) {
			Boolean check = StringUtils.isNotBlank(userId)
					&& StringUtils.isNotBlank(token)
					&& StringUtils.isNotBlank(tenantId)
					&& (userId.equals(ActionContextHolder.getEvaHolder().get(token).getId()
							.toString()))
					&& (user.getTenant().getId().equals(Long.valueOf(tenantId))); // 不能跨租户发请求
			if (check) {
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 验证后台是否登录
	 *
	 * @param request
	 * @return flag
	 */
	public boolean checkBackStandUser(HttpServletRequest request) {
		Boolean flag = false;
		HttpSession session = request.getSession();
		UserPrivate user = (UserPrivate) session.getAttribute("user");
		if (user != null) {
			Role role = user.getRole();
			if (role != null) {
				String roleCode = role.getCode();
				if (roleCode.equals("admin")) {
					flag = true;
				} else if (roleCode.equals("operator")) {
					flag = true;
				} else if (roleCode.equals("system")) {
					flag = true;
				}
			}
		}

		return flag;
	}

	/**
	 * 查看是否需要token验证
	 */
	public boolean checkIsVerify(HttpServletRequest request) {
		boolean flag = true;
		if (request.getRequestURI().startsWith("/api/userSession")
				|| request.getRequestURI().startsWith("/api/authCode")) {// 登录注册验证吗
			flag = false;
		} else if (request.getRequestURI().equals("/api/user")) { // 根据登录名或code查询用户
			if (StringUtils.isNotBlank(request.getParameter("filter[loginName]"))
					|| StringUtils.isNotBlank(request.getParameter("filter[code@$or1]"))) {
				flag = false;
			}
		} else if (request.getRequestURI().equals("/api/task")
				&& (StringUtils.isNotBlank(request.getParameter("filter[code@$or1]")))) { // 根据code查询任务
			flag = false;
		} else if (request.getRequestURI().equals("/api/dicttype")) { // 字典数据放行
			flag = false;
		} else if (request.getRequestURI().equals("/api/sysconfig")) { // 请求放行
			flag = false;
		}
		return flag;
	}

}
